<?php
/**
 * @license http://www.gnu.org/licenses/lgpl.html LGPL
 * @author Harlan Iverson <h dot iverson at gmail dot com>
 * @copyright Copyright (c) 2006, Harlan Iverson.
 * @version $Id: PhpFaces.php 20 2006-08-01 05:54:40Z Harlan $
 */
 

require_once( "PhpFaces/FacesConfig.php" );
require_once( "PhpFaces/FacesContext.class.php" );
require_once( "PhpFaces/Lifecycle.php" );
require_once( "PhpFaces/ViewHandler.class.php" );
require_once( "HTML/Template/Smarty/Smarty.class.php" );



/**
 * A class with one static method to conveniently run PhpFaces
 */
class PhpFaces {
	
	static function SetupEnvironment( $configFile ) {
		$config = new PhpFaces_FacesConfig( $configFile );
		$config->parse();
		
		foreach( $config->getRequiredFiles() as $file ) {
			require_once( $file );
		}
		
		$lifecycleFactory = PhpFaces_LifecycleFactory::GetInstance();
		$lifecycle = $lifecycleFactory->getLifecycle( "default" );
		
		$lifecycle->setConfig( $config );
		

	
		// ************************** ATTN ****************************
		// all classes required to deserialize the session must
		// be included by this point!
		// ************************** ATTN ****************************
		session_start();
		
		
		$facesContext =& PhpFaces_FacesContext::getCurrentInstance();

		// FIXME I'm not sure where in the cycle
		// this should take place... 		
		foreach( $config->getManagedBeans() as $managedBean ) {
			$facesContext->registerBean( $managedBean->name, $managedBean->class, $managedBean->scope );
		}
		
		foreach( $config->getNavigationRules() as $navigationRule ) {
			$facesContext->registerNavigationRule( $navigationRule );
		}
		
		foreach( $config->getPhaseListeners() as $phaseListenerClass) {
			$phaseListener = new $phaseListenerClass;
			$lifecycle->addPhaseListener( $phaseListener );
		}

		
		
		return $facesContext;
	}
	
	
	/**
	 * Run PhpFaces given a config file. Does all stages of the request and
	 * all loading of dependencies, execution of actions, etc. Lots to talk about here.
	 * @param $configFile string the path to a faces-config.xml
	 */
	static function RunFaces( $configFile = null ) {
		
		$facesContext = null;
		if( $configFile != null ) {
			$facesContext = self::SetupEnvironment( $configFile );
		} else {
			$facesContext =& PhpFaces_FacesContext::getCurrentInstance();
		}
		
		$lifecycleFactory = PhpFaces_LifecycleFactory::GetInstance();
		$lifecycle = $lifecycleFactory->getLifecycle( "default" );
		
		$lifecycle->execute( $facesContext );
		//
		// Handle View
		// PhpFaces_ViewHandler
		//
		$lifecycle->render( $facesContext );
	}
}

/**
 * The default view handler for PhpFaces; runs Facelets parsing on top of Smarty.
 */
class PhpFaces_ViewHandler {
	/**
	 * Runs the View Handler on a given context
	 * @todo this could be abstracted a bit more
	 */
	public function run( PhpFaces_FacesContext $facesContext ) {

		$smarty = new Smarty();
		call_user_func( array("PhpFaces_FaceletsTemplateResource", "register"),  $smarty );	
		
		$page = $_REQUEST["page"];
	
		$title = "No Title";
		$section = "home";
		$stylesheets = array( "main.css" );
	
	
		if( file_exists( "controller/$page.php") ) {
			ob_start();
			// don't capture output, this just populates smarty
			include( "content/$page.php" );
			ob_end_clean();
		}
		
		if( file_exists( $smarty->template_dir."/pages/$page.tpl") ) {
			
			$smarty->assign("styleSheets", $stylesheets);
			
			$output = $smarty->fetch( "pages/$page.tpl" );
		} else if( file_exists( $smarty->template_dir."/pages/$page.jsf") ) {
			$smarty->assign("styleSheets", $stylesheets);
			
			$output = $smarty->fetch( "facelets://pages/$page.jsf" );
		} else if( file_exists( "content/$page.php" ) ) {
			ob_start();
			include( "content/$page.php" );
			$pageData = ob_get_contents();
			ob_end_clean();
			
			$smarty->assign("title", $title);
			$smarty->assign("section", $section);
			$smarty->assign("styleSheets", $stylesheets);
			
			$smarty->assign("pageContent", $pageData);
			$output = $smarty->fetch( isset($template)?$template:"layouts/realtime-quote.tpl" );
		} else {
			header( "Status: 404" );
			$smarty->assign("styleSheets", $stylesheets);
			$output = $smarty->fetch( "pages/404.tpl" );
		}
	
		echo $output;
	}
	
}

/**
 * The default navigation handler.
 */
class PhpFaces_NavigationHandler {
	/**
	 * Run the navigation handler on given FacesContext
	 */
	public function run( PhpFaces_FacesContext $facesContext ) {
		$navigationRules = $facesContext->getNavigationRules();

		$fromOutcome = $facesContext->runAction( $_POST );
	
		$fromViewId = ""; // TODO
		$fromAction = $facesContext->getCurrentActionName( $_POST );

		//echo "ran action [".$fromAction."] from view [$fromViewId], outcome = $fromOutcome";
		
		foreach( $navigationRules as $navigationRule ) {
			$doesFromViewIdMatch = ($navigationRule->fromViewId == null || $navigationRule->fromViewId == $fromViewId);
			$doesFromActionMatch = ($navigationRule->fromAction == null || $navigationRule->fromAction == $fromAction);
			$doesFromOutcomeMatch = ($navigationRule->fromOutcome == null || $navigationRule->fromOutcome == $fromOutcome);
			
			$handlerMatches = $doesFromViewIdMatch && $doesFromActionMatch && $doesFromOutcomeMatch;
			
			if( $handlerMatches )	{
				//print_r( $navigationRule );
				$redirectTo = linkUrl( $navigationRule->toViewId );
				//echo "redirectTo = $navigationRule->toViewId = $redirectTo";
				header( "Location: $redirectTo" );
				//virtual( $redirectTo );
				//print_r( $fc );
				
				exit();
				
			}
		}

	}	
}
?>